#include "../ls7a_config.h"
#include "../ls7a.h"

#include "ls3a7a_setup_ht_link.c"
#include "ls7a.c"
#include "ls3a7a_win.c"
#include "ls7a_gmem_config.c"

pcie_phy_param_t def_phy_cfg = {0xc2492331, 0x73e70b0, 0x20000};
pcie_desc ls7a_pcie_ctrl[] = {
	{0x0efe08004800, 0,  "F0", 0xf, LS7A_PCIE_F0_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x0efe08006800, 4,  "F1", 0x3, LS7A_PCIE_F1_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x0efe08009800, 6,  "H ", 0x3, LS7A_PCIE_H_DISABLE , &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x0efe08007800, 8,  "G0", 0x3, LS7A_PCIE_G0_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x0efe08008800, 10, "G1", 0x3, LS7A_PCIE_G1_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
#if (TOT_7A_NUM == 2)
	/* For 3A5000_16w dual LS7A */
	{0x5efe08004800, 0,  "F0", 0xf, LS7A_ANOTHER_PCIE_F0_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x5efe08006800, 4,  "F1", 0x3, LS7A_ANOTHER_PCIE_F1_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x5efe08009800, 6,  "H ", 0x3, LS7A_ANOTHER_PCIE_H_DISABLE , &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x5efe08007800, 8,  "G0", 0x3, LS7A_ANOTHER_PCIE_G0_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
	{0x5efe08008800, 10, "G1", 0x3, LS7A_ANOTHER_PCIE_G1_DISABLE, &def_phy_cfg, LS7A_PCIE_ADAPT_MODE},
#endif
};

sata_desc ls7a_sata_ctrl[] = {
	{LS7A_SATA0_DISABLE, 0, 0x403f1002},
	{LS7A_SATA1_DISABLE, 0, 0x403f1002},
	{LS7A_SATA2_DISABLE, 0, 0x403f1002},
};

usb_desc ls7a_usb_ctrl[] = {
	{LS7A_USB0_DISABLE, 0, 0x02f80dc9, 0, 0x02f80dc9, 0, 0x02f80dc9},
	{LS7A_USB1_DISABLE, 1, 0x02f80dc9, 1, 0x02f80dc9, 1, 0x02f80dc9},
};

gmac_desc ls7a_gmac_ctrl[] = {
	{LS7A_GMAC0_DISABLE},
	{LS7A_GMAC1_DISABLE},
};

void ls7a_pll_adapt(ls7a_pll_table* pll_ctrl)
{
	/*pcie, gmac, sata/usb*/
	pll_ctrl[LS7A_PLL0].pll_val = LS7A_PLL_VALUE(80, 8, 16, 12);
	pll_ctrl[LS7A_PLL0].div = 4;
	/*gpu, gmem, dc*/
	pll_ctrl[LS7A_PLL1].pll_val = (ls7a_version() ? LS7A_PLL_VALUE(120, 5, 5, 12) : LS7A_PLL_VALUE(127, 8, 6, 12));
	pll_ctrl[LS7A_PLL1].div = 4;
	/*flex, node, hda bitclk*/
	pll_ctrl[LS7A_PLL2].pll_val = LS7A_PLL_VALUE(96, 72, (ls7a_version() ? 4 : 6), 100);
	pll_ctrl[LS7A_PLL2].div = 4;
	/*PIX0, default 38.2MHz for x800x600*/
	pll_ctrl[LS7A_PLL3].pll_val = LS7A_PLL_VALUE(104, 68, 68, 68);
	pll_ctrl[LS7A_PLL3].div = 4;
	/*PIX1, default 38.2MHz for x800x600*/
	pll_ctrl[LS7A_PLL4].pll_val = LS7A_PLL_VALUE(104, 68, 68, 68);
	pll_ctrl[LS7A_PLL4].div = 4;
#if	(TOT_NODE_NUM == 16)
	//7a 2w
	/*pcie, gmac, sata/usb*/
	pll_ctrl[LS7A1_PLL0].pll_val = LS7A_PLL_VALUE(80, 8, 16, 12);
	pll_ctrl[LS7A1_PLL0].div = 4;
	/*flex, node, hda bitclk*/
	pll_ctrl[LS7A1_PLL0].pll_val = LS7A_PLL_VALUE(96, 72, (ls7a_version() ? 4 : 6), 100);
	pll_ctrl[LS7A1_PLL0].div = 4;
#endif
}

void ls7a_feature_init(void)
{
#ifdef LS7A_2WAY_CONNECT
	ls7a_cfg_t.ht.ls7a_2way_connect = 1;
#else
	ls7a_cfg_t.ht.ls7a_2way_connect = 0;
#endif
	ls7a_cfg_t.ht.ls7a_node_num = TOT_7A_NUM;
	ls7a_cfg_t.ht.ls3a_node_num = TOT_NODE_NUM;

	//pll
	ls7a_pll_adapt(ls7a_cfg_t.pll);

	//pcie
	ls7a_cfg_t.pcie.ref_clk = USE_INSIDE_REFCLK;
	ls7a_cfg_t.pcie.x8_cal_en = ENABLE_PCIEX8_CAL;
	ls7a_cfg_t.pcie.controller = ls7a_pcie_ctrl;

	//sata
	ls7a_cfg_t.sata.ref_clk = USE_INSIDE_REFCLK;
	ls7a_cfg_t.sata.controller = ls7a_sata_ctrl;

	//usb
	ls7a_cfg_t.usb.ref_clk = USE_INSIDE_REFCLK;
	ls7a_cfg_t.usb.controller = ls7a_usb_ctrl;

	//gmac
	ls7a_cfg_t.gmac.ref_clk = USE_INSIDE_REFCLK;
	ls7a_cfg_t.gmac.controller = ls7a_gmac_ctrl;

	//display
	ls7a_cfg_t.dc.graphics_disable = LS7A_GRAPHICS_DISABLE;
	ls7a_cfg_t.dc.gmem_cfg = LS7A_GMEM_CFG;

	//misc devices
	ls7a_cfg_t.misc.lpc_disable = LS7A_LPC_DISABLE;
	ls7a_cfg_t.misc.fan.min_rpm = 5000;
	ls7a_cfg_t.misc.fan.min_rpm = 10000;
}

void ls7a_init(void)
{
	int status;
	//Initialize LS7A here
	pr_info("Ls7A init begain\n");
	ls3a7a_ht_config();

#ifdef DEBUG_ENABLE_LOONGSON
	pr_info("------------------Test Ls7a access-----------------\n");
	status = ls7a_dbg();
	if (status) {
		pr_info("Test Ls7a access fail!\n");
		while(1);
	}
#endif

	ls7a_resource_cfg(&ls7a_cfg_t);
	loongson_ht_trans_init();

	if (ls7a_version()) {
		/*Debug New 7A Func,Drop Rtc voltage*/
		do {
			readl(LS7A_ACPI_PMCON_RTC_REG) |= (0x3 << 9);
		} while (((readl(LS7A_ACPI_PMCON_RTC_REG) >> 9) & 0x3) != 0x3);
	}
	ls7a_clear_pcie_portirq();
	pr_info("Ls7A1000 Chipset initialize done.\n");
}
